package com.dy.yunying.biz.service.datacenter.impl;

import cn.hutool.core.io.FileUtil;
import cn.hutool.crypto.digest.DigestUtil;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.dy.yunying.api.dto.audience.AudiencePackDto;
import com.dy.yunying.api.entity.ParentGameDO;
import com.dy.yunying.api.vo.audience.AudiencePack;
import com.dy.yunying.api.vo.audience.AudiencePackVo;
import com.dy.yunying.biz.config.YunYingProperties;
import com.dy.yunying.biz.dao.datacenter.impl.AudiencePackDao;
import com.dy.yunying.biz.dao.manage.ParentGameDOMapper;
import com.dy.yunying.biz.service.datacenter.AudiencePackService;
import com.dy.yunying.biz.utils.DateUtils;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.pig4cloud.pig.api.entity.SelfCustomAudience;
import com.pig4cloud.pig.api.feign.RemoteSelfAudienceService;
import com.pig4cloud.pig.common.core.constant.SecurityConstants;
import com.pig4cloud.pig.common.core.util.R;
import com.pig4cloud.pig.common.security.util.SecurityUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.io.File;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description
 * @Author chengang
 * @Date 2022/7/18
 */
@Log4j2
@Service
@RequiredArgsConstructor
public class AudiencePackServiceImpl implements AudiencePackService {

	private final AudiencePackDao audiencePackDao;

	private final RemoteSelfAudienceService remoteSelfAudienceService;

	private final ParentGameDOMapper parentGameDOMapper;

	private final YunYingProperties yunYingProperties;

	@Override
	public AudiencePack page(AudiencePackDto dto, boolean isPage) {
		//获取总条数--查询太慢了，单独写接口
		//Long total = audiencePackDao.selectCount(dto,false);
		//if (total != null && total.longValue() > 0) {
		List<AudiencePackVo> list = audiencePackDao.selectByPage(dto,isPage);
			// 填充父游戏名称
			// 去重后的主游戏不会很多，暂时不用分页去查询
			List<Long> pIds = list.stream().map(AudiencePackVo::getPgid)
					.distinct()
					.map(v -> Long.valueOf(v))
					.filter(Objects::nonNull)
					.collect(Collectors.toList());
			Map<Long, String> mapping = pIds.isEmpty() ? Collections.emptyMap() : parentGameDOMapper.selectList(Wrappers.<ParentGameDO>lambdaQuery()
					.select(ParentGameDO::getId, ParentGameDO::getGname)
					.in(ParentGameDO::getId, pIds))
					.stream()
					.collect(Collectors.toMap(ParentGameDO::getId, ParentGameDO::getGname, (k1, k2) -> k1));
			list.forEach(e -> {
				e.setPgidName(StringUtils.defaultIfBlank(mapping.get(Long.valueOf(e.getPgid())), "-"));
				e.setMobile("-");
			});
//		}
		return new AudiencePack(list,0L,dto.getSize(),dto.getCurrent());
	}

	@Override
	public AudiencePack count(AudiencePackDto dto, boolean isPage) {
		Long total = audiencePackDao.selectCount(dto,isPage);
		return new AudiencePack(new ArrayList<>(),total,dto.getSize(),dto.getCurrent());
	}

	@Override
	public R pack(AudiencePackDto dto) {
		try {
			//根据条件获取自有人群集合
			AudiencePack audience = this.page(dto,false);

			//获取到需要打包的字段
			List<String> fieldList = Lists.newArrayList();
			List<String> fieldListResult = this.setData(audience.getList(), dto.getType(), fieldList);

			if (ObjectUtils.isEmpty(fieldListResult)) {
				return R.failed("当前选择字段内容为空，打包失败");
			}
			// 这里仅仅上传TXT文件，压缩逻辑和分多个txt逻辑在自有人群包推送逻辑中处理

			//生成TXT文件 打包字段不为空的 可以生成txt文件
			Map<String, Object> result = this.genTxtFile(fieldListResult);

			// 因头条现在压缩包大小为 50M，广点通现在为 100M，故上传TXT暂时限制100M
			File txtFile = (File) result.get("file");


			if (this.checkFileSize4Gdt(txtFile)) {
				//文件大于100M，需要删除文件
				FileUtil.del(txtFile);
				return R.failed("文件内容不能大于100M");
			}

			//持久化到DB
			SelfCustomAudience entity = new SelfCustomAudience();
			entity.setName(dto.getPackageName());
			entity.setType(dto.getType());
			entity.setDataCount((Integer) result.get("fileSize"));
			entity.setDownloadUrl((String) result.get("downLoadUrl"));
			entity.setCreateId(Long.valueOf(SecurityUtils.getUser().getId()));
			entity.setUpdateId(Long.valueOf(SecurityUtils.getUser().getId()));
			boolean flag = remoteSelfAudienceService.saveEntity(SecurityConstants.FROM_IN,entity);
			if (flag) {
				return R.ok();
			} else {
				return R.failed("打包失败，打包记录保存失败");
			}
		} catch (Exception e) {
			e.printStackTrace();
			log.error(e.getMessage());
			return R.failed("打包失败，请稍后再试。");
		}
	}

	private Map<String, Object> genTxtFile(List<String> fieldListResult) {
		Map<String, Object> resultMap = Maps.newHashMap();
		String ymPath = DateUtils.dateToString(new Date(), DateUtils.YYYYMMDD) + "/";
		UUID uid = UUID.randomUUID();
		String uuid = String.valueOf(uid);
		String realName = uuid + ".txt";
		String filePath = yunYingProperties.getUploadPath() + ymPath + realName;
		String downLoadUrl = yunYingProperties.getDownloadUrl() + ymPath + realName;
		File file = FileUtil.writeLines(fieldListResult, filePath, "UTF-8");

		resultMap.put("downLoadUrl", downLoadUrl);
		resultMap.put("fileSize", fieldListResult.size());
		resultMap.put("file", file);

		return resultMap;
	}

	private List<String> setData(List<AudiencePackVo> list, Integer type, List<String> fieldList) {
		switch (type) {
			case 0:
				fieldList = list.stream().map(AudiencePackVo::getImei).filter(v-> StringUtils.isNotBlank(v)).collect(Collectors.toList());
				break;
			case 1:
				fieldList = list.stream().map(AudiencePackVo::getIdfa).filter(v-> StringUtils.isNotBlank(v)).collect(Collectors.toList());
				break;
			case 2:
				//自有人群包没有UID字段
				Lists.newArrayList();
				break;
			case 4:
				List<String> tmpImei = list.stream().map(AudiencePackVo::getImei).filter(v-> StringUtils.isNotBlank(v)).collect(Collectors.toList());
				fieldList = tmpImei.stream().map(v -> DigestUtil.md5Hex(v.toLowerCase())).collect(Collectors.toList());
				break;
			case 5:
				List<String> tmpIdfa = list.stream().map(AudiencePackVo::getIdfa).filter(v-> StringUtils.isNotBlank(v)).collect(Collectors.toList());
				fieldList = tmpIdfa.stream().map(v -> DigestUtil.md5Hex(v.toUpperCase())).collect(Collectors.toList());
				break;
			case 6:
				List<String> tmpMobile = list.stream().map(AudiencePackVo::getMobile).filter(v-> StringUtils.isNotBlank(v)).collect(Collectors.toList());
				fieldList = tmpMobile.stream().map(v -> DigestUtil.sha256Hex(v)).collect(Collectors.toList());
				break;
			case 7:
				fieldList = list.stream().map(AudiencePackVo::getOaid).filter(v-> StringUtils.isNotBlank(v)).collect(Collectors.toList());
				break;
			case 8:
				List<String> tmpOaid = list.stream().map(AudiencePackVo::getOaid).filter(v-> StringUtils.isNotBlank(v)).collect(Collectors.toList());
				fieldList = tmpOaid.stream().map(v -> DigestUtil.md5Hex(v.toLowerCase())).collect(Collectors.toList());
				break;
			case 9:
				List<String> tmpMobileMd5 = list.stream().map(AudiencePackVo::getMobile).filter(v-> StringUtils.isNotBlank(v)).collect(Collectors.toList());
				fieldList = tmpMobileMd5.stream().map(v -> DigestUtil.md5Hex(v)).collect(Collectors.toList());
				break;
			case 10:
				fieldList = list.stream().map(AudiencePackVo::getMac).filter(v-> StringUtils.isNotBlank(v)).collect(Collectors.toList());
				break;
			default:
				log.error("不支持的打包类型-{}", type);
		}
		return fieldList;
	}

	private Boolean checkFileSize4Gdt(File file) {
		long Kb = 1 * 1024;
		long Mb = Kb * 1024;
		long Gb = Mb * 1024;
		long size = FileUtil.size(file);
		if (size >= Mb && size < Gb) {
			double len = file.length() / Mb;
			if (len > 100) {
				return true;
			}
		}
		return false;
	}

}
